/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-05-27 15:44:52
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-08-21 15:57:58
 * @FilePath: /vue3-uniapp/src/plugins/uvuiTools.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import UvuiTools from '@climblee/uv-ui';
import { Subject } from 'rxjs';

import type {
    RouteOption,
    UvRouter,
    RouteType
} from '@/typings/declaration/uvUi';
import { getCurrentRoute, getPage } from '@/utils/route';

export type BeforeRouteLeaveHookState = {
    to: string;
    from: string;
};

export type BeforeEachState = RouteOption & {
    to: string;
    from: string;
    _index: number;
};

const beforeRouteLeaveSubject = new Subject<BeforeRouteLeaveHookState>();
const beforeEachSubject = new Subject<BeforeEachState>();
let nextState: BeforeEachState | undefined;
let count = 0; // beforeEachSubject的订阅数

const excuteTo = (option: RouteOption) => {
    let to = option.url;
    if (to === undefined) {
        if (['back', 'navigateBack'].includes(option.type || '')) {
            const page = getPage(-2);
            to = `/${page?.route}`;
        } else {
            throw new Error(
                '[./plugins/uvuiTools]url为空则type必须为back或navigateBack'
            );
        }
    }
    return to;
};

export const setupUvuiTools: SetupFunc = (app) => {
    app?.use(UvuiTools, {});
    const route = uni.$uv.route;
    const router = (option: RouteOption) => {
        try {
            const from = getCurrentRoute();

            if (typeof from !== 'string') {
                throw new Error('[uvui]无法获取当前路由路径');
            }
            const to = excuteTo(option);
            beforeRouteLeaveSubject.next({
                from,
                to
            });
            if (count === 0) {
                route(option);
            } else {
                nextState = {
                    ...option,
                    to,
                    from,
                    _index: 0
                };
                beforeEachSubject.next(JSON.parse(JSON.stringify(nextState)));
            }
        } catch (e) {
            console.log(e);
        }
    };
    // 组件内导航守卫
    router.onBeforeRouteLeave = ((fn) => {
        let from = '';
        const subscription = beforeRouteLeaveSubject.subscribe((state) => {
            from = state.from;
            fn(state);
        });
        return subscription;
        // if (onBeforeUnmount) {
        //     onBeforeUnmount(() => {
        //         subscription.unsubscribe();
        //         console.log(`[${from}]onBeforeRouteLeave订阅者释放`);
        //     });
        // }
    }) as UvRouter['onBeforeRouteLeave'];
    // 全局或组件内导航守卫
    router.onBeforeEach = ((fn) => {
        count += 1;
        let from = '';
        const subscription = beforeEachSubject.subscribe({
            next: (originOption) => {
                if (!nextState) {
                    throw new Error(
                        '[uvui]rxjs设计初衷是支持并发和独立处理，请勿异步调用next'
                    );
                }
                const index = nextState._index;
                const next = (opt?: RouteOption) => {
                    try {
                        if (!nextState) {
                            throw new Error(
                                '[uvui]rxjs设计初衷是支持并发和独立处理，请勿异步调用next'
                            );
                        }
                        if (index + 1 < count) {
                            if (opt && nextState) {
                                const to = excuteTo(opt);
                                nextState = {
                                    ...nextState,
                                    ...opt,
                                    to
                                };
                            }
                        } else {
                            if (nextState) {
                                from = nextState.from;
                                route(nextState); // 跳转
                                nextState = undefined;
                            }
                        }
                    } catch (e) {
                        console.log(e);
                    }
                };
                fn({
                    ...originOption,
                    ...nextState,
                    next
                });
                nextState._index += 1;
            }
        });
        // if (onBeforeUnmount) {
        //     onBeforeUnmount(() => {
        //         count -= 1;
        //         subscription.unsubscribe();
        //         console.log(`[${from}]onBeforeEach订阅者释放`);
        //     });
        // }
        return subscription;
    }) as UvRouter['onBeforeEach'];
    uni.$uv.route = router;
};
